package com.gmall.pay.controller;

import com.github.wxpay.sdk.WXPayUtil;
import com.gmall.common.result.Result;
import com.gmall.pay.service.WXPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.Map;

@RestController
@RequestMapping("api/pay/wxpay")
public class PayController {


    @Autowired
    WXPayService wxPayService;

    /**
     * http://localhost:8080/api/pay/wxpay/notifyUrl
     * 数据流
     * 多次
     * 支付完成后，微信会把相关支付结果及用户信息通过 【数据流】 的形式发送给商户，商户需要接收处理，并按文档规范返回应答。
     * 注意：
     * 1、同样的通知可能会 【多次】 发送给商户系统。商户系统必须能够正确处理重复的通知。
     * 2、后台通知交互时，如果微信收到商户的应答不符合规范或超时，微信会判定本次通知失败，重新发送通知，
     * 直到成功为止（在通知一直不成功的情况下，微信总共会发起多次通知，通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m）这里通知发送可能会多台服务器进行发送，且发送时间可能会在几秒内，但微信不保证通知最终一定能成功。
     *
     * 3、在订单状态不明或者没有收到微信支付结果通知的情况下，建议商户主动调用微信支付【查询订单API】确认订单状态。
     *
     * 特别提醒：
     * 1、商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄露导致出现“假通知”，造成资金损失。
     *
     * 2、当收到通知进行处理时，首先检查对应业务数据的状态，判断该通知是否已经处理过，如果没有处理过再进行处理，如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前，要采用数据锁进行并发控制，以避免函数重入造成的数据混乱。
     */
    @PostMapping("notifyUrl")
    public void notifyUrl(HttpServletRequest request,
                          HttpServletResponse response) throws Exception {
        System.out.println("------->" + new Date());

        InputStream inputStream = request.getInputStream();

        // IO
        //字节
        //InputStream OutputStream
        //字符
        //Reader Writer
        //转换流
        //InputStreamReader 输入的是inputStream 返回的Reader
        //OutputStreamWriter 输入的是outputStream 返回的Writer

        Reader reader = new InputStreamReader(inputStream, "UTF-8");//适配器设计模式
        BufferedReader bufferedReader = new BufferedReader(reader);//包装者设计模式

        StringBuilder stringBuilder = new StringBuilder();
        bufferedReader.lines().forEach(line->{
                stringBuilder.append(line);
            }
        );

        String xml = stringBuilder.toString();
        System.out.println(xml);
        Map<String, String> stringStringMap = WXPayUtil.xmlToMap(xml);

        String orderId = stringStringMap.get("out_trade_no");

        System.out.println("OrderId------->"+ orderId);
        OutputStream outputStream = response.getOutputStream();

        Writer writer = new OutputStreamWriter(outputStream,"UTF-8");
        BufferedWriter bufferedWriter = new BufferedWriter(writer);

        bufferedWriter.write("<xml>\n" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                "</xml>");//网络中write写在缓存中，并没有从网卡口写出

        wxPayService.paySuccess(Long.parseLong(orderId));


        bufferedWriter.flush();//强制将缓存中的数据从内存写出到网卡口

        bufferedReader.close();
        bufferedWriter.close();//关闭流，释放资源

    }

    @PostMapping("unifiedorder/{orderId}/{amount}")
    public Result<Map> unifiedorder(@PathVariable String orderId,
                                    @PathVariable Integer amount) throws Exception {

        return wxPayService.unifiedorder(orderId, amount);
    }

    @GetMapping("orderquery/{orderId}")
    public Result<Map> orderquery(@PathVariable Long orderId) throws Exception {

        return wxPayService.orderquery(orderId);
    }

}
